/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package main.pso;

import java.util.Random;

import main.Centroid;
import main.DataVector;
import main.Particle;
import main.Util;
import main.Velocity;

/**
 *
 * @author Amigao
 */
public class HPSOM extends PSO{
    private int mutationPercent = 0;

    public HPSOM(String fileName){
        super(fileName);
    }

    public HPSOM(String filePath, int mutacao) {
        super(filePath);
        mutationPercent = mutacao;
    }
    
    @Override
    public void execute(int k, int numberOfParticles, int numberOfIterations) {
        this.euclidianDistances = new double[k];

		this.initializeTrainingSet();

		this.initializeParticles(k, numberOfParticles);

		for (int i = 0; i <= numberOfIterations; i++) {

			for (Particle particle : this.swarm) {

				for (DataVector trainningData : trainningSet) {

					for (int j = 0; j < particle.getCentroids().length; j++) {
						this.euclidianDistances[j] = Util
								.calculateEuclidianDistance(trainningData,
										particle.getCentroids()[j]);
					}

					this.assignTrainningDataToNearestCentroid(trainningData,
							particle);

				}

				particle.calculateFitness();

				particle.updateLocalBestPosition();

			}

			this.updateGlobalBestPosition();

			double w = wMin + (i * ((wMax-wMin)/numberOfIterations));
			this.updateParticlesPositions(w);

		}

		this.evaluate(k, globalBestPosition);

    }

    @Override
    public void initializeParticles(int k, int numberOfParticles) {

		Particle particle = null;
		Centroid centroid = null;
		Velocity velocity = null;

		// para cada particula
		for (int i = 0; i < numberOfParticles; i++) {
			// inicializa a particula
			particle = new Particle(i, k);

			// para cada centroide na particula
			for (int j = 0; j < k; j++) {

				centroid = new Centroid(j, this.trainningSet.get(0)
						.getPosition().length);
				velocity = new Velocity(
						this.trainningSet.get(0).getPosition().length);
				// atribue a posi��o de um elemento aleat�tio do trainingSet ao
				// valor da posi��o do centr�ide
				centroid.setPosition(trainningSet.get(
						random.nextInt(trainningSet.size())).getPosition()
						.clone());

				for (int l = 0; l < centroid.getPosition().length; l++) {
					// o valor da velocidade � um valor aleat�rio em cada
					// particula.
					velocity.getVelocities()[l] = random.nextDouble();
                    //System.out.println(velocity.getVelocities()[l]);
				}

				particle.getCentroids()[j] = centroid;
				particle.getVelocities()[j] = velocity;

			}
			// adiciona a particula criada ao enxame
			this.swarm.add(particle);

		}

	}
    protected void updateParticlesPositions(double w) {
    	
    	double porcentagem = (double)mutationPercent/100;
    	for (Particle particle : swarm) {
			double teste = random.nextDouble();
            if(porcentagem >= teste){
            	this.mutate(particle);
                
            }else{
                this.calculateVelocity(particle,w);
                particle.updatePosition();
            }
		}
		
	}

    
}
